using System.Collections;
using System.Collections.Generic;
using System.Xml.Linq;
using UnityEngine;
using UnityEngine.Events;
/// <summary>
/// 知识点
/// 1.AB包相关的API
/// 2.单例模式
/// 3.委托->Lambda表达式
/// 4.协程
/// 5.字典
/// </summary>
public class ABMgr : SingletonMono<ABMgr>
{
    //AB包管理器 目的是
    //让外部更方便的进行资源加载

    private AssetBundle mainAB = null;
    //依赖包获取用的配置
    private AssetBundleManifest manifest = null;

    //AB包不能重复加载
    //字典 用字典来存储 加载过的AB包
    private Dictionary<string, AssetBundle> abDic = new Dictionary<string, AssetBundle>();

    /// <summary>
    /// AB包存放路径 方便修改
    /// </summary>
    private string PathUrl
    {
        get
        {
            return Application.streamingAssetsPath + "/";
        }
    }

    /// <summary>
    /// 主包名 方便修改
    /// </summary>
    private string MainABName
    {
        get
        {
#if UNITY_IOS
                return "IOS";
#elif UNITY_ANDROID
                return "Android";
#else
            return "PC";
#endif
        }
    }

    private void LoadAB(string name)
    {
        //加载AB包
        if (mainAB == null)
        {
            mainAB = AssetBundle.LoadFromFile(PathUrl + MainABName);
            manifest = mainAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
        }
        //获取依赖包相关信息
        string[] strs = manifest.GetAllDependencies(name);
        AssetBundle ab;
        for (int i = 0; i < strs.Length; i++)
        {
            //判断包是否加载过
            if (!abDic.ContainsKey(strs[i]))
            {
                ab = AssetBundle.LoadFromFile(PathUrl + strs[i]);
                abDic.Add(strs[i], ab);
            }
        }
        //加载资源来源包,判断重复加载
        if (!abDic.ContainsKey(name))
        {
            ab = AssetBundle.LoadFromFile(PathUrl + name);
            abDic.Add(name, ab);
        }
    }

    /// <summary>
    /// 同步加载(不指定类型)
    /// </summary>
    /// <param name="abName"></param>
    /// <param name="resName"></param>
    /// <returns></returns>
    public Object LoadRes(string abName, string resName)
    {
        LoadAB(abName);
        //加载资源
        return abDic[abName].LoadAsset(resName);
    }

    /// <summary>
    /// 同步加载(指定类型)
    /// </summary>
    /// <param name="abName"></param>
    /// <param name="resName"></param>
    /// <returns></returns>
    public Object LoadRes(string abName, string resName, System.Type type)
    {
        LoadAB(abName);
        Object obj = abDic[abName].LoadAsset(resName, type);
        return obj;
    }

    /// <summary>
    /// 同步加载(泛型)
    /// </summary>
    /// <param name="abName"></param>
    /// <param name="resName"></param>
    /// <param name="type"></param>
    /// <returns></returns>
    public Object LoadRes<T>(string abName, string resName) where T : Object
    {
        LoadAB(abName);
        Object obj = abDic[abName].LoadAsset<T>(resName);
        return obj;
    }

    /// <summary>
    /// 异步加载(根据名称加载)
    /// 注:这里的异步加载,AB包没有使用异步加载,只是从AB包中加载资源时 使用异步
    /// </summary>
    /// <param name="abName"></param>
    public void LoadResAnsync(string abName, string resName, UnityAction<Object> callback)
    {
        StartCoroutine(ReallyLoadResAsync(abName, resName, callback));
    }

    private IEnumerator ReallyLoadResAsync(string abName, string resName, UnityAction<Object> callback)
    {
        LoadAB(abName);
        AssetBundleRequest abr = abDic[abName].LoadAssetAsync(resName);
        yield return abr;
        callback(abr.asset);
    }

    /// <summary>
    /// 异步加载(根据Type加载)
    /// 注:这里的异步加载,AB包没有使用异步加载,只是从AB包中加载资源时 使用异步
    /// </summary>
    /// <param name="abName"></param>
    public void LoadResAnsync(string abName, string resName, System.Type type, UnityAction<Object> callback)
    {
        StartCoroutine(ReallyLoadResAsync(abName, resName, type, callback));
    }

    private IEnumerator ReallyLoadResAsync(string abName, string resName, System.Type type, UnityAction<Object> callback)
    {
        LoadAB(abName);
        AssetBundleRequest abr = abDic[abName].LoadAssetAsync(resName, type);
        yield return abr;
        callback(abr.asset);
    }

    /// <summary>
    /// 异步加载(根据Type加载)
    /// 注:这里的异步加载,AB包没有使用异步加载,只是从AB包中加载资源时 使用异步
    /// </summary>
    /// <param name="abName"></param>
    public void LoadResAnsync<T>(string abName, string resName, UnityAction<Object> callback) where T : Object
    {
        StartCoroutine(ReallyLoadResAsync<T>(abName, resName, callback));
    }

    private IEnumerator ReallyLoadResAsync<T>(string abName, string resName, UnityAction<Object> callback) where T : Object
    {
        LoadAB(abName);
        AssetBundleRequest abr = abDic[abName].LoadAssetAsync<T>(resName);
        yield return abr;
        callback(abr.asset as T);
    }


    //单个包卸载
    public void UnLoad(string abName)
    {
        if (abDic.ContainsKey(name))
        {
            abDic[abName].Unload(false);
            abDic.Remove(abName);
        }
    }

    //所有包的卸载
    public void ClearAB(string abName)
    {
        AssetBundle.UnloadAllAssetBundles(false);
        abDic.Clear();
        mainAB = null;
        manifest = null;
    }
}